from flask import Flask, jsonify, request, send_file, make_response, Response
from flask_cors import CORS
import pandas as pd
from datetime import datetime
import numpy as np
import plotly.graph_objs as go
import plotly.io as pio
import plotly.utils
import json

app = Flask(__name__)
CORS(app)  # 启用CORS支持

# 读取CSV文件
df = pd.read_csv('historical_weather_daily.csv')

# 处理日期列
df['日期'] = pd.to_datetime(df['日期'].str.split(' ').str[0])
df['年份'] = df['日期'].dt.year
df['月份'] = df['日期'].dt.month

# 处理风向和风力数据
def process_wind_data(wind_str):
    try:
        if pd.isna(wind_str):
            return pd.NA, pd.NA
        parts = str(wind_str).split(' ')
        if len(parts) >= 2:
            direction = parts[0]
            level = parts[1].replace('级', '')
            return direction, int(level)
        return pd.NA, pd.NA
    except:
        return pd.NA, pd.NA

# 应用处理函数
df[['风向', '风力']] = df['风向'].apply(process_wind_data).apply(pd.Series)

# 清理数据：移除无效的风向风力数据
df = df.dropna(subset=['风向', '风力'])

@app.route('/api/years', methods=['GET'])
def get_years():
    """获取所有可用的年份"""
    years = sorted(df['年份'].unique().tolist())
    return jsonify(years)

@app.route('/api/months', methods=['GET'])
def get_months():
    """获取所有可用的月份"""
    months = sorted(df['月份'].unique().tolist())
    return jsonify(months)

@app.route('/api/weather', methods=['GET'])
def get_weather():
    """根据年份和月份获取天气数据"""
    year = request.args.get('year', type=int)
    month = request.args.get('month', type=int)
    
    if not year or not month:
        return jsonify({'error': '请提供年份和月份参数'}), 400
    
    # 筛选数据
    filtered_df = df[(df['年份'] == year) & (df['月份'] == month)]
    
    if filtered_df.empty:
        return jsonify({'error': '未找到相关数据'}), 404
    
    # 转换数据为列表格式
    weather_data = filtered_df.to_dict('records')
    
    # 处理日期格式
    for record in weather_data:
        record['日期'] = record['日期'].strftime('%Y-%m-%d')
        # 重新组合风向和风力
        record['风向'] = f"{record['风向']} {record['风力']}级"
    
    return jsonify(weather_data)

@app.route('/api/statistics', methods=['GET'])
def get_statistics():
    """获取天气统计数据"""
    year = request.args.get('year', type=int)
    month = request.args.get('month', type=int)
    
    if not year or not month:
        return jsonify({'error': '请提供年份和月份参数'}), 400
    
    # 筛选数据
    filtered_df = df[(df['年份'] == year) & (df['月份'] == month)]
    
    if filtered_df.empty:
        return jsonify({'error': '未找到相关数据'}), 404
    
    # 计算统计数据
    stats = {
        '平均最高温': round(filtered_df['最高气温'].str.replace('℃', '').astype(float).mean(), 1),
        '平均最低温': round(filtered_df['最低气温'].str.replace('℃', '').astype(float).mean(), 1),
        '最高温度': round(filtered_df['最高气温'].str.replace('℃', '').astype(float).max(), 1),
        '最低温度': round(filtered_df['最低气温'].str.replace('℃', '').astype(float).min(), 1),
        '天气类型统计': filtered_df['天气'].value_counts().to_dict(),
        '风向统计': filtered_df['风向'].value_counts().to_dict()
    }
    
    return jsonify(stats)

@app.route('/api/weather-pie', methods=['GET'])
def get_weather_pie():
    """获取天气类型饼图数据"""
    year = request.args.get('year', type=int)
    month = request.args.get('month', type=int)
    
    if not year or not month:
        return jsonify({'error': '请提供年份和月份参数'}), 400
    
    filtered_df = df[(df['年份'] == year) & (df['月份'] == month)]
    
    if filtered_df.empty:
        return jsonify({'error': '未找到相关数据'}), 404
    
    # 统计天气类型
    weather_stats = filtered_df['天气'].value_counts()
    
    # 转换为饼图数据格式
    pie_data = [{'name': k, 'value': v} for k, v in weather_stats.items()]
    
    return jsonify(pie_data)

@app.route('/api/wind-rose', methods=['GET'])
def get_wind_rose():
    """获取风向玫瑰图数据"""
    year = request.args.get('year', type=int)
    month = request.args.get('month', type=int)
    
    if not year or not month:
        return jsonify({'error': '请提供年份和月份参数'}), 400
    
    filtered_df = df[(df['年份'] == year) & (df['月份'] == month)]
    
    if filtered_df.empty:
        return jsonify({'error': '未找到相关数据'}), 404
    
    # 按风向和风力分组统计
    wind_stats = filtered_df.groupby(['风向', '风力']).size().reset_index(name='count')
    
    # 转换为玫瑰图数据格式
    rose_data = []
    for _, row in wind_stats.iterrows():
        rose_data.append({
            'name': f"{row['风向']} {row['风力']}级",
            'value': int(row['count']),
            'direction': row['风向'],
            'level': int(row['风力'])
        })
    
    return jsonify(rose_data)

@app.route('/api/line-chart')
def line_chart():
    try:
        year = request.args.get('year', type=int)
        month = request.args.get('month', type=int)
        filtered_df = df[(df['年份'] == year) & (df['月份'] == month)]
        if filtered_df.empty:
            return Response(json.dumps({'data': [], 'layout': {}}), mimetype='application/json')
        trace1 = go.Scatter(x=filtered_df['日期'], y=filtered_df['最高气温'].str.replace('℃','').astype(float), mode='lines+markers', name='最高气温')
        trace2 = go.Scatter(x=filtered_df['日期'], y=filtered_df['最低气温'].str.replace('℃','').astype(float), mode='lines+markers', name='最低气温')
        layout = go.Layout(title='温度变化趋势', xaxis=dict(title='日期'), yaxis=dict(title='温度(℃)'))
        return Response(
            json.dumps({'data': [trace1.to_plotly_json(), trace2.to_plotly_json()], 'layout': layout.to_plotly_json()}, cls=plotly.utils.PlotlyJSONEncoder),
            mimetype='application/json'
        )
    except Exception as e:
        return Response(json.dumps({'data': [], 'layout': {}, 'error': str(e)}), mimetype='application/json')

@app.route('/api/pie-chart')
def pie_chart():
    try:
        year = request.args.get('year', type=int)
        month = request.args.get('month', type=int)
        filtered_df = df[(df['年份'] == year) & (df['月份'] == month)]
        if filtered_df.empty:
            return Response(json.dumps({'data': [], 'layout': {}}), mimetype='application/json')
        weather_counts = filtered_df['天气'].value_counts()
        trace = go.Pie(labels=weather_counts.index, values=weather_counts.values)
        layout = go.Layout(title='天气类型分布')
        return Response(
            json.dumps({'data': [trace.to_plotly_json()], 'layout': layout.to_plotly_json()}, cls=plotly.utils.PlotlyJSONEncoder),
            mimetype='application/json'
        )
    except Exception as e:
        return Response(json.dumps({'data': [], 'layout': {}, 'error': str(e)}), mimetype='application/json')

@app.route('/api/rose-chart')
def rose_chart():
    try:
        year = request.args.get('year', type=int)
        month = request.args.get('month', type=int)
        filtered_df = df[(df['年份'] == year) & (df['月份'] == month)]
        if filtered_df.empty:
            return Response(json.dumps({'data': [], 'layout': {}}), mimetype='application/json')
        wind_stats = filtered_df.groupby(['风向', '风力']).size().reset_index(name='count')
        labels = wind_stats.apply(lambda row: f"{row['风向']} {row['风力']}级", axis=1)
        trace = go.Barpolar(
            r=wind_stats['count'],
            theta=labels,
            name='风向风力分布',
            marker_color='rgb(106,81,163)'
        )
        layout = go.Layout(
            title='风向风力分布',
            polar=dict(
                radialaxis=dict(showticklabels=True, ticks=''),
            ),
            showlegend=False
        )
        return Response(
            json.dumps({'data': [trace.to_plotly_json()], 'layout': layout.to_plotly_json()}, cls=plotly.utils.PlotlyJSONEncoder),
            mimetype='application/json'
        )
    except Exception as e:
        return Response(json.dumps({'data': [], 'layout': {}, 'error': str(e)}), mimetype='application/json')

if __name__ == '__main__':
    app.run(debug=True, port=5000) 